package Server

import (
	"BackEnd/common/Neo4j"
	"BackEnd/common/Python"
	"encoding/json"
	"fmt"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"io"
	"log"
	"net/http"
	"regexp"
)

// InitServer 服务器初始化
func InitServer() *gin.Engine {
	// 创建服务
	TheServer := gin.Default()
	TheServer.Use(cors.Default())
	// 函数注册
	registerRoutes(TheServer)
	// 指定服务器端口
	err := TheServer.Run(serverAddr)
	if err != nil {
		log.Println(err)
		return nil
	}

	return TheServer
}

// 函数注册
func registerRoutes(TheServer *gin.Engine) {
	var methodToHandlerMap = make(map[string][]RouteFunc)
	for _, route := range routes {
		methodToHandlerMap[route.HTTPMethod] = append(methodToHandlerMap[route.HTTPMethod], route)
	}

	for _, route := range methodToHandlerMap["GET"] {
		TheServer.GET(route.Route, route.Func)
	}

	for _, route := range methodToHandlerMap["POST"] {
		TheServer.POST(route.Route, route.Func)
	}
}

// 解析PDF到图数据库
func fileAnalyze(c *gin.Context) {
	// 获取上传的文件
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "获取文件失败"})
		return
	}
	defer file.Close()

	// 获取文件名（如果用户上传了文件）
	fileName := "NewFile"
	if header != nil && header.Filename != "" {
		fileName = header.Filename
	}

	// 将文件内容读取为[]byte
	content, err := io.ReadAll(file)
	if err != nil {
		fmt.Println("Read file as bytes fail")
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Read file as bytes fail"})
		return
	}

	// 调用分析接口
	err, response := Python.AnalyzeFile(c, fileName, content)
	if err != nil {
		log.Printf("[Fail]: AnalyzeFile %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "AnalyzeFile fail"})
		return
	}

	// 获取解析文件的图数据库标签
	label := response.Label
	// 用此标签查询图数据库
	queryString := fmt.Sprintf("MATCH (n1)-[r]->(n2) WHERE n1:%s AND n2:%s RETURN n1, r, n2 LIMIT 100", label, label)
	err, graphData := Neo4j.Query(queryString)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Query Neo4j fail"})
		return
	}

	// 设置响应头
	c.Header("Content-Type", "text/event-stream")
	c.Header("Cache-Control", "no-cache")

	flusher, ok := c.Writer.(http.Flusher)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Streaming not supported"})
		return
	}

	totalNodes := len(graphData.Nodes) // 总节点数
	totalEdges := len(graphData.Edges) // 总关系数
	batchSize := 10                    // 每批次发送数据量

	// 节点
	nodesData := graphData.Nodes
	// 边
	edgesData := graphData.Edges

	// 发送节点数据（分批）
	for i := 0; i < totalNodes; i += batchSize {
		end := i + batchSize
		if end > totalNodes {
			end = totalNodes
		}

		nodes := map[string]interface{}{
			"type":  "nodes",
			"nodes": nodesData[i:end],
		}

		if err := sendJSON(c, nodes); err != nil {
			log.Printf("发送节点数据失败: %v", err)
			return
		}
		flusher.Flush()
	}

	// 分批发送边
	for i := 0; i < totalEdges; i += batchSize {
		end := i + batchSize
		if end > totalEdges {
			end = totalEdges
		}

		edges := map[string]interface{}{
			"type":  "edges",
			"edges": edgesData[i:end],
		}

		if err := sendJSON(c, edges); err != nil {
			log.Printf("发送边数据失败: %v", err)
			return
		}
		flusher.Flush()
	}

	// 发送结束事件
	endEvent := map[string]interface{}{
		"type": "done",
		"data": "[DONE]",
	}
	if err := sendJSON(c, endEvent); err != nil {
		log.Printf("[Fail]: EndEvent, %v", err)
	}
	flusher.Flush()

	return
}

// 回答用户提问
func answerQuestion(c *gin.Context) {
	var body RequestBody
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 从表单获取问题
	question := body.Question
	fmt.Println("[Question]:", question)

	// 调用Python服务获取查询语句和提示词
	err, resp := Python.GetGraphData(c, question)
	fmt.Println(resp)
	if err != nil {
		log.Printf("[Fail]: GetGraphData %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Invoke GetGraphData fail"})
	}

	// 从Python端获取回答
	cue := []string{question, resp.Answer}
	err, answer := Python.GetAnswer(c, cue)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Invoke GetAnswer fail"})
		return
	}

	// 转化查询语句为返回节点和边类型的
	// 正则表达式匹配模式
	pattern := `MATCH\s*\((\w*):sanguo\s*\{name:\s*'([^']+)'\}\)-\s*\[:([^\]]+)\]\s*->\((\w*):sanguo\)\s*RETURN\s*\w+\.\w+`
	re := regexp.MustCompile(pattern)
	// 替换为新的格式
	replacement := `MATCH (n1:sanguo {name: '$2'})-[r:$3]->(n2:sanguo) RETURN n1, r, n2`
	// 执行替换
	queryString := re.ReplaceAllString(resp.CypherStatement, replacement)

	// 查询图数据库
	err, graphData := Neo4j.Query(queryString)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Query Neo4j fail"})
		return
	}

	// 设置响应头
	c.Header("Content-Type", "text/event-stream")
	c.Header("Cache-Control", "no-cache")

	flusher, ok := c.Writer.(http.Flusher)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Streaming not supported"})
		return
	}

	// 发送回答
	textEvent := map[string]interface{}{
		"type":    "text",
		"content": answer.Text,
	}
	if err := sendJSON(c, textEvent); err != nil {
		log.Printf("[Fail]: sendJSON, %v", err)
		return
	}
	flusher.Flush()

	totalNodes := len(graphData.Nodes) // 总节点数
	totalEdges := len(graphData.Edges) // 总关系数
	batchSize := 10                    // 每批次发送数据量

	// 节点
	nodesData := graphData.Nodes
	// 边
	edgesData := graphData.Edges

	// 发送节点数据（分批）
	for i := 0; i < totalNodes; i += batchSize {
		end := i + batchSize
		if end > totalNodes {
			end = totalNodes
		}

		nodes := map[string]interface{}{
			"type":  "nodes",
			"nodes": nodesData[i:end],
		}

		if err := sendJSON(c, nodes); err != nil {
			log.Printf("发送节点数据失败: %v", err)
			return
		}
		flusher.Flush()
	}

	// 分批发送边
	for i := 0; i < totalEdges; i += batchSize {
		end := i + batchSize
		if end > totalEdges {
			end = totalEdges
		}

		edges := map[string]interface{}{
			"type":  "edges",
			"edges": edgesData[i:end],
		}

		if err := sendJSON(c, edges); err != nil {
			log.Printf("发送边数据失败: %v", err)
			return
		}
		flusher.Flush()
	}

	// 发送结束事件
	endEvent := map[string]interface{}{
		"type": "done",
		"data": "[DONE]",
	}
	if err := sendJSON(c, endEvent); err != nil {
		log.Printf("[Fail]: EndEvent, %v", err)
	}
	flusher.Flush()

	return
}

// 发送JSON数据到响应流
func sendJSON(c *gin.Context, data interface{}) error {
	jsonData, err := json.Marshal(data)
	if err != nil {
		return err
	}

	// 添加换行符作为分隔符
	jsonData = append(jsonData, '\n')

	_, err = c.Writer.Write(jsonData)
	return err
}
